
#include <stdio.h>  
#include <netinet/in.h>
#include <unistd.h>
#include <sys/socket.h>
#include "opencv2/opencv.hpp"
#include "Ffmpeg_Decode.h"
using namespace cv;

typedef struct socket_info
{
	int serSocket;
	int numClient;
	sockaddr_in remoteAddr[10];
	//int nAddrLen[10];
	socklen_t nAddrLen[10];

}Socket_Udp_Server_Info;

Socket_Udp_Server_Info * initUdpServer()
{
	int i = 0;
	Socket_Udp_Server_Info * mSocketInfo = (Socket_Udp_Server_Info *)malloc(sizeof(Socket_Udp_Server_Info));

	mSocketInfo->serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (mSocketInfo->serSocket == -1)
	{
		printf("socket error !");
		return 0;
	}

	sockaddr_in serAddr;
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(8888);
	serAddr.sin_addr.s_addr = INADDR_ANY;
	if (bind(mSocketInfo->serSocket, (sockaddr *)&serAddr, sizeof(serAddr)) == -1)
	{
		printf("bind error !");
		close(mSocketInfo->serSocket);
		return 0;
	}
	else
	{
		printf("bind succeed  ! \n");
	}
	mSocketInfo->nAddrLen[0] = sizeof(sockaddr_in);

	return mSocketInfo;
}

// 结束时候调用
void unitUdpServer(Socket_Udp_Server_Info * mSocketInfo)
{
	close(mSocketInfo->serSocket);
}


long consumptiontime;
long playframecount = 0;
int main()
{

	Socket_Udp_Server_Info * mSocketUdpServerInfo = initUdpServer();

	int info[3];
	int flag = 0;
	int ret = 0;
	printf("wait for video flag...\n");
	ret = recvfrom(mSocketUdpServerInfo->serSocket, (char *)info, sizeof(int) * 3, 0,
		(sockaddr *)&mSocketUdpServerInfo->remoteAddr[0], &mSocketUdpServerInfo->nAddrLen[0]);
	int width = info[0];
	int height = info[1];
	int channel = info[2];
	int bufferSize = width * height * channel;
	flag = 1;
	printf("flag re succeed w=%d h=%d c=%d \n", width, height, channel);
	if (ret == sizeof(int))
	{
		printf("flag re succeed \n");
	}
	char * revBuffer = (char *)malloc(sizeof(char) * bufferSize);
	Mat reviMat = Mat(height, width, CV_8UC3);

	Ffmpeg_Decoder ffmpegobj;
	ffmpegobj.Ffmpeg_Decoder_Init();

	while (1)
	{
        usleep(1);
		ffmpegobj.nDataLen = recvfrom(mSocketUdpServerInfo->serSocket, revBuffer, bufferSize, 0, 
                                      (sockaddr *)&mSocketUdpServerInfo->remoteAddr[0], &mSocketUdpServerInfo->nAddrLen[0]);
		//ffmpegobj.nDataLen = recv(mSocketTcpServerInfo->sClient[0], revBuffer, bufferSize, 0);
		memcpy(ffmpegobj.filebuf, revBuffer, ffmpegobj.nDataLen);

		printf("server ret = %d \n", ffmpegobj.nDataLen);

        //if(ffmpegobj.nDataLen != 1400)
        //    continue;

		if (ffmpegobj.nDataLen <= 0)
		{
			
            //houlc
            printf("[Error]ffmpegobj.nDataLen <=0 \n");
			//break;
            continue;
		}
		else
		{
			ffmpegobj.haveread = 0;
			while (ffmpegobj.nDataLen > 0)
			{
                usleep(1);
				printf("[houlc-debug] av_parser_parse2..start..\n");
				int nLength = av_parser_parse2(ffmpegobj.avParserContext, ffmpegobj.c, &ffmpegobj.yuv_buff,
					&ffmpegobj.nOutSize, ffmpegobj.filebuf + ffmpegobj.haveread, ffmpegobj.nDataLen, 0, 0, 0);//查找帧头
				printf("[houlc-debug] av_parser_parse2..ok..ret=%d\n", ffmpegobj.nOutSize);
				ffmpegobj.nDataLen -= nLength;//查找过后指针移位标志
				ffmpegobj.haveread += nLength;
				if (ffmpegobj.nOutSize <= 0)
				{

					break;
				}
				ffmpegobj.avpkt.size = ffmpegobj.nOutSize;//将帧数据放进包中
				ffmpegobj.avpkt.data = ffmpegobj.yuv_buff;
				playframecount++;

                usleep(1);
				printf("[houlc-debug] avcodec_decode_video2..start..\n");
				ffmpegobj.decodelen = avcodec_decode_video2(ffmpegobj.c, ffmpegobj.m_pYUVFrame, &ffmpegobj.piclen, &ffmpegobj.avpkt);//解码
				printf("[houlc-debug] avcodec_decode_video2..ret:%d.\n", ffmpegobj.decodelen);

				printf("[houlc-debug] AVERROR_BUG=%ld\n", AVERROR_BUG);
                if(ffmpegobj.piclen<0)
				{
					printf("\n[houlc]decode len < 0!!!!\n");
					break;
				}
				if (ffmpegobj.piclen)
				{
					if (ffmpegobj.finishInitScxt == false)//初始化格式转换函数  
					{
						ffmpegobj.finishInitScxt = true;
						ffmpegobj.scxt = sws_getContext(ffmpegobj.c->width, ffmpegobj.c->height, ffmpegobj.c->pix_fmt,
							ffmpegobj.c->width, ffmpegobj.c->height, AV_PIX_FMT_BGR24, SWS_POINT, NULL, NULL, NULL);

						int width = ffmpegobj.c->width;
						int height = ffmpegobj.c->height;
						ffmpegobj.yuv_buff = new uint8_t[width * height * 2];//初始化YUV图像数据区
						ffmpegobj.rgb_buff = new uint8_t[width * height * 3];//初始化RGB图像帧数据区
						ffmpegobj.data[0] = ffmpegobj.rgb_buff;
						ffmpegobj.linesize[0] = width * 3;
					}
					if (ffmpegobj.scxt != NULL)
					{
                        usleep(1);
						//YUV转rgb  
						sws_scale(ffmpegobj.scxt, ffmpegobj.m_pYUVFrame->data, ffmpegobj.m_pYUVFrame->linesize, 0,
							ffmpegobj.c->height, ffmpegobj.data, ffmpegobj.linesize);

                        usleep(1);
						ffmpegobj.Ffmpeg_Decoder_Show((char*)ffmpegobj.rgb_buff, ffmpegobj.c->width, ffmpegobj.c->height);//解码图像显示   	
					}
				}
			}
		}


	}
	printf("消耗时间%dms\n", clock() - consumptiontime);//消耗时间计算
	printf("平均1s解码帧数%lf\n", playframecount / ((clock() - consumptiontime) / (double)1000));//消耗时间计算
	printf("解码帧数%d\n", playframecount);

	ffmpegobj.Ffmpeg_Decoder_Close();//关闭解码器
	return 0;
}

